"""
高德地图MCP服务工具类
提供路线规划功能，支持步行、骑车、公共交通和自驾
"""

import logging
import requests
import json
from typing import Dict, List, Optional, Any
from enum import Enum

from utils.config import Config

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class TravelMode(Enum):
    """出行方式枚举"""
    WALKING = "walking"  # 步行
    BICYCLING = "bicycling"  # 骑车
    TRANSIT = "transit"  # 公共交通
    DRIVING = "driving"  # 自驾

class AmapTool:
    """高德地图工具类，提供路线规划功能"""
    
    def __init__(self):
        """初始化高德地图工具"""
        # 验证配置
        Config.validate_config()
        
        self.api_key = Config.AMAP_API_KEY
        self.base_url = "https://restapi.amap.com/v3"
        
        if not self.api_key:
            raise ValueError("AMAP_API_KEY 环境变量未设置")
        
        logger.info("高德地图工具初始化完成")
    
    def _make_request(self, endpoint: str, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        发送HTTP请求到高德地图API
        
        Args:
            endpoint: API端点
            params: 请求参数
            
        Returns:
            API响应数据
        """
        try:
            # 添加API密钥
            params['key'] = self.api_key
            params['output'] = 'json'
            
            url = f"{self.base_url}/{endpoint}"
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            
            if data.get('status') != '1':
                error_msg = data.get('info', '未知错误')
                logger.error(f"高德地图API错误: {error_msg}")
                return {'error': error_msg}
            
            return data
            
        except requests.exceptions.RequestException as e:
            logger.error(f"请求高德地图API时出错: {str(e)}")
            return {'error': f'网络请求失败: {str(e)}'}
        except json.JSONDecodeError as e:
            logger.error(f"解析API响应时出错: {str(e)}")
            return {'error': f'响应解析失败: {str(e)}'}
        except Exception as e:
            logger.error(f"调用高德地图API时出错: {str(e)}")
            return {'error': f'API调用失败: {str(e)}'}
    
    def geocode_address(self, address: str, city: str = None) -> Dict[str, Any]:
        """
        地理编码：将地址转换为经纬度坐标
        
        Args:
            address: 地址
            city: 城市（可选）
            
        Returns:
            包含坐标信息的字典
        """
        logger.info(f"正在地理编码地址: {address}")
        
        params = {
            'address': address
        }
        if city:
            params['city'] = city
        
        data = self._make_request('geocode/geo', params)
        
        if 'error' in data:
            return data
        
        geocodes = data.get('geocodes', [])
        if not geocodes:
            return {'error': '未找到该地址的坐标信息'}
        
        # 返回第一个结果
        geocode = geocodes[0]
        location = geocode.get('location', '').split(',')
        
        if len(location) != 2:
            return {'error': '坐标格式错误'}
        
        return {
            'address': geocode.get('formatted_address', address),
            'longitude': float(location[0]),
            'latitude': float(location[1]),
            'province': geocode.get('province', ''),
            'city': geocode.get('city', ''),
            'district': geocode.get('district', ''),
            'level': geocode.get('level', '')
        }
    
    def reverse_geocode(self, longitude: float, latitude: float) -> Dict[str, Any]:
        """
        逆地理编码：将经纬度坐标转换为地址
        
        Args:
            longitude: 经度
            latitude: 纬度
            
        Returns:
            包含地址信息的字典
        """
        logger.info(f"正在逆地理编码坐标: {longitude}, {latitude}")
        
        params = {
            'location': f"{longitude},{latitude}"
        }
        
        data = self._make_request('geocode/regeo', params)
        
        if 'error' in data:
            return data
        
        regeocode = data.get('regeocode', {})
        if not regeocode:
            return {'error': '未找到该坐标的地址信息'}
        
        address_component = regeocode.get('addressComponent', {})
        
        return {
            'formatted_address': regeocode.get('formatted_address', ''),
            'province': address_component.get('province', ''),
            'city': address_component.get('city', ''),
            'district': address_component.get('district', ''),
            'township': address_component.get('township', ''),
            'neighborhood': address_component.get('neighborhood', {}).get('name', ''),
            'building': address_component.get('building', {}).get('name', '')
        }
    
    def plan_route(self, origin: str, destination: str, mode: TravelMode, 
                   city: str = None, waypoints: List[str] = None) -> Dict[str, Any]:
        """
        规划路线
        
        Args:
            origin: 起点地址
            destination: 终点地址
            mode: 出行方式
            city: 城市（可选）
            waypoints: 途经点列表（可选）
            
        Returns:
            路线规划结果
        """
        logger.info(f"正在规划路线: {origin} -> {destination}, 方式: {mode.value}")
        
        # 获取起点和终点的坐标
        origin_geocode = self.geocode_address(origin, city)
        if 'error' in origin_geocode:
            return {'error': f'起点地址解析失败: {origin_geocode["error"]}'}
        
        dest_geocode = self.geocode_address(destination, city)
        if 'error' in dest_geocode:
            return {'error': f'终点地址解析失败: {dest_geocode["error"]}'}
        
        origin_coord = f"{origin_geocode['longitude']},{origin_geocode['latitude']}"
        dest_coord = f"{dest_geocode['longitude']},{dest_geocode['latitude']}"
        
        # 根据出行方式选择不同的API端点
        if mode == TravelMode.WALKING:
            return self._plan_walking_route(origin_coord, dest_coord, origin_geocode, dest_geocode)
        elif mode == TravelMode.BICYCLING:
            return self._plan_bicycling_route(origin_coord, dest_coord, origin_geocode, dest_geocode)
        elif mode == TravelMode.TRANSIT:
            return self._plan_transit_route(origin_coord, dest_coord, origin_geocode, dest_geocode, city)
        elif mode == TravelMode.DRIVING:
            return self._plan_driving_route(origin_coord, dest_coord, origin_geocode, dest_geocode, waypoints)
        else:
            return {'error': f'不支持的出行方式: {mode.value}'}
    
    def _plan_walking_route(self, origin_coord: str, dest_coord: str, 
                           origin_info: Dict, dest_info: Dict) -> Dict[str, Any]:
        """规划步行路线"""
        params = {
            'origin': origin_coord,
            'destination': dest_coord,
            'strategy': '0'  # 最短距离
        }
        
        data = self._make_request('direction/walking', params)
        
        if 'error' in data:
            return data
        
        route = data.get('route', {})
        paths = route.get('paths', [])
        
        if not paths:
            return {'error': '未找到步行路线'}
        
        path = paths[0]
        
        return {
            'mode': 'walking',
            'origin': origin_info,
            'destination': dest_info,
            'distance': int(path.get('distance', 0)),
            'duration': int(path.get('duration', 0)),
            'steps': self._parse_walking_steps(path.get('steps', [])),
            'summary': {
                'total_distance': f"{int(path.get('distance', 0)) / 1000:.2f}公里",
                'total_duration': f"{int(path.get('duration', 0)) // 60}分钟"
            }
        }
    
    def _plan_bicycling_route(self, origin_coord: str, dest_coord: str, 
                             origin_info: Dict, dest_info: Dict) -> Dict[str, Any]:
        """规划骑车路线"""
        params = {
            'origin': origin_coord,
            'destination': dest_coord,
            'strategy': '0'  # 最短距离
        }
        
        data = self._make_request('direction/bicycling', params)
        
        if 'error' in data:
            return data
        
        route = data.get('route', {})
        paths = route.get('paths', [])
        
        if not paths:
            return {'error': '未找到骑车路线'}
        
        path = paths[0]
        
        return {
            'mode': 'bicycling',
            'origin': origin_info,
            'destination': dest_info,
            'distance': int(path.get('distance', 0)),
            'duration': int(path.get('duration', 0)),
            'steps': self._parse_bicycling_steps(path.get('steps', [])),
            'summary': {
                'total_distance': f"{int(path.get('distance', 0)) / 1000:.2f}公里",
                'total_duration': f"{int(path.get('duration', 0)) // 60}分钟"
            }
        }
    
    def _plan_transit_route(self, origin_coord: str, dest_coord: str, 
                           origin_info: Dict, dest_info: Dict, city: str = None) -> Dict[str, Any]:
        """规划公共交通路线"""
        params = {
            'origin': origin_coord,
            'destination': dest_coord,
            'strategy': '0',  # 最快捷模式
            'nightflag': '0'  # 非夜班车
        }
        
        if city:
            params['city'] = city
        
        data = self._make_request('direction/transit/integrated', params)
        
        if 'error' in data:
            return data
        
        route = data.get('route', {})
        transits = route.get('transits', [])
        
        if not transits:
            return {'error': '未找到公共交通路线'}
        
        # 返回前3个方案
        transit_plans = []
        for transit in transits[:3]:
            plan = {
                'cost': float(transit.get('cost', 0)),
                'duration': int(transit.get('duration', 0)),
                'walking_distance': int(transit.get('walking_distance', 0)),
                'segments': self._parse_transit_segments(transit.get('segments', []))
            }
            transit_plans.append(plan)
        
        return {
            'mode': 'transit',
            'origin': origin_info,
            'destination': dest_info,
            'plans': transit_plans,
            'summary': {
                'total_cost': f"{transit_plans[0]['cost']:.2f}元" if transit_plans else "0元",
                'total_duration': f"{transit_plans[0]['duration'] // 60}分钟" if transit_plans else "0分钟",
                'walking_distance': f"{transit_plans[0]['walking_distance'] / 1000:.2f}公里" if transit_plans else "0公里"
            }
        }
    
    def _plan_driving_route(self, origin_coord: str, dest_coord: str, 
                           origin_info: Dict, dest_info: Dict, waypoints: List[str] = None) -> Dict[str, Any]:
        """规划自驾路线"""
        params = {
            'origin': origin_coord,
            'destination': dest_coord,
            'strategy': '0'  # 最快路线
        }
        
        if waypoints:
            waypoint_coords = []
            for waypoint in waypoints:
                waypoint_geocode = self.geocode_address(waypoint)
                if 'error' not in waypoint_geocode:
                    waypoint_coords.append(f"{waypoint_geocode['longitude']},{waypoint_geocode['latitude']}")
            if waypoint_coords:
                params['waypoints'] = '|'.join(waypoint_coords)
        
        data = self._make_request('direction/driving', params)
        
        if 'error' in data:
            return data
        
        route = data.get('route', {})
        paths = route.get('paths', [])
        
        if not paths:
            return {'error': '未找到自驾路线'}
        
        # 返回前3个方案
        driving_plans = []
        for path in paths[:3]:
            plan = {
                'distance': int(path.get('distance', 0)),
                'duration': int(path.get('duration', 0)),
                'traffic_lights': int(path.get('traffic_lights', 0)),
                'tolls': float(path.get('tolls', 0)),
                'toll_distance': int(path.get('toll_distance', 0)),
                'steps': self._parse_driving_steps(path.get('steps', []))
            }
            driving_plans.append(plan)
        
        return {
            'mode': 'driving',
            'origin': origin_info,
            'destination': dest_info,
            'plans': driving_plans,
            'summary': {
                'total_distance': f"{driving_plans[0]['distance'] / 1000:.2f}公里" if driving_plans else "0公里",
                'total_duration': f"{driving_plans[0]['duration'] // 60}分钟" if driving_plans else "0分钟",
                'tolls': f"{driving_plans[0]['tolls']:.2f}元" if driving_plans else "0元"
            }
        }
    
    def _parse_walking_steps(self, steps: List[Dict]) -> List[Dict[str, Any]]:
        """解析步行路线步骤"""
        parsed_steps = []
        for step in steps:
            parsed_steps.append({
                'instruction': step.get('instruction', ''),
                'distance': int(step.get('distance', 0)),
                'duration': int(step.get('duration', 0)),
                'road': step.get('road', ''),
                'orientation': step.get('orientation', '')
            })
        return parsed_steps
    
    def _parse_bicycling_steps(self, steps: List[Dict]) -> List[Dict[str, Any]]:
        """解析骑车路线步骤"""
        parsed_steps = []
        for step in steps:
            parsed_steps.append({
                'instruction': step.get('instruction', ''),
                'distance': int(step.get('distance', 0)),
                'duration': int(step.get('duration', 0)),
                'road': step.get('road', ''),
                'orientation': step.get('orientation', '')
            })
        return parsed_steps
    
    def _parse_transit_segments(self, segments: List[Dict]) -> List[Dict[str, Any]]:
        """解析公共交通路线段"""
        parsed_segments = []
        for segment in segments:
            segment_info = {
                'walking': segment.get('walking', {}),
                'bus': segment.get('bus', {}),
                'railway': segment.get('railway', {}),
                'taxi': segment.get('taxi', {})
            }
            parsed_segments.append(segment_info)
        return parsed_segments
    
    def _parse_driving_steps(self, steps: List[Dict]) -> List[Dict[str, Any]]:
        """解析自驾路线步骤"""
        parsed_steps = []
        for step in steps:
            parsed_steps.append({
                'instruction': step.get('instruction', ''),
                'distance': int(step.get('distance', 0)),
                'duration': int(step.get('duration', 0)),
                'road': step.get('road', ''),
                'orientation': step.get('orientation', ''),
                'tolls': float(step.get('tolls', 0))
            })
        return parsed_steps
    
    def get_route_summary(self, route_result: Dict[str, Any]) -> str:
        """
        获取路线规划摘要信息
        
        Args:
            route_result: 路线规划结果
            
        Returns:
            格式化的摘要信息
        """
        if 'error' in route_result:
            return f"路线规划失败: {route_result['error']}"
        
        mode = route_result.get('mode', '')
        origin = route_result.get('origin', {}).get('address', '')
        destination = route_result.get('destination', {}).get('address', '')
        
        summary_lines = [
            f"出行方式: {self._get_mode_display_name(mode)}",
            f"起点: {origin}",
            f"终点: {destination}",
            ""
        ]
        
        if mode in ['walking', 'bicycling']:
            summary = route_result.get('summary', {})
            summary_lines.extend([
                f"总距离: {summary.get('total_distance', '未知')}",
                f"预计时间: {summary.get('total_duration', '未知')}"
            ])
        elif mode == 'transit':
            summary = route_result.get('summary', {})
            summary_lines.extend([
                f"预计时间: {summary.get('total_duration', '未知')}",
                f"费用: {summary.get('total_cost', '未知')}",
                f"步行距离: {summary.get('walking_distance', '未知')}"
            ])
        elif mode == 'driving':
            summary = route_result.get('summary', {})
            summary_lines.extend([
                f"总距离: {summary.get('total_distance', '未知')}",
                f"预计时间: {summary.get('total_duration', '未知')}",
                f"过路费: {summary.get('tolls', '未知')}"
            ])
        
        return "\n".join(summary_lines)
    
    def _get_mode_display_name(self, mode: str) -> str:
        """获取出行方式的中文显示名称"""
        mode_names = {
            'walking': '步行',
            'bicycling': '骑车',
            'transit': '公共交通',
            'driving': '自驾'
        }
        return mode_names.get(mode, mode)
    
    def batch_plan_routes(self, route_requests: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        批量规划路线
        
        Args:
            route_requests: 路线规划请求列表，每个请求包含origin, destination, mode等参数
            
        Returns:
            路线规划结果列表
        """
        results = []
        for request in route_requests:
            origin = request.get('origin')
            destination = request.get('destination')
            mode_str = request.get('mode', 'driving')
            city = request.get('city')
            waypoints = request.get('waypoints')
            
            # 转换出行方式字符串为枚举
            try:
                mode = TravelMode(mode_str)
            except ValueError:
                results.append({'error': f'不支持的出行方式: {mode_str}'})
                continue
            
            result = self.plan_route(origin, destination, mode, city, waypoints)
            results.append(result)
        
        logger.info(f"批量处理了 {len(route_requests)} 个路线规划请求")
        return results
